#define _GNU_SOURCE

#include "syscore.h"
#include "sqlite3.h"
#include <stdlib.h>
#include "common.h"
#include <time.h>
#include <limits.h>
#include "../logServer/clogger.h"
#define DATAPLogDebug(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_DEBUG, fmt, ##args);
#define DATAPLogInfo(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_INFO, fmt, ##args);
#define DATAPLogNotice(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_NOTICE, fmt, ##args);
#define DATAPLogWarning(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_WARNING, fmt, ##args);
#define DATAPLogError(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_ERR, fmt, ##args);
#define DATAPLogCrit(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_CRIT, fmt, ##args);
#define DATAPLogAlert(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_ALERT, fmt, ##args);
#define DATAPLogEmerg(fmt, args...) CLogger(MODULE_DATAPRO, __FILE__, __LINE__, LOG_EMERG, fmt, ##args);

typedef enum tagLISTTYPE{
    BLACK = 0,
    WHITE,
    INVALID_LISTTYPE
}LISTTYPE;

typedef enum tagRECORDTYPE {
    IMSI = 0,
    IMEI,
    INVALID_RECTYPE
}RECORDTYPE;

typedef enum tagPOSTPROCCMD {
    NULL_CMD = 0,
    START_DFC
} POSTPROCCMD;

typedef struct tagDATAPROCSTATS {
    U32 numUEIDRecvd;
    U32 numUEIDforwarded;
    U32 numUEIDforwardFailed;
    U32 numBlackAlertSent;
    U32 numBlackAlertSendFailed;
    U32 numWhiteDropped;
    
}DATAPROCSTATS;
#define MAX_DATAPROC_RECORDS 150
#define DATAPROC_TIMER_RESOLUTION 1000
#define DATAPROC_HAERTBEAT_INTERVAL 5000
#define DATAPROC_DATASEND_INTERVAL 1000
#define DATAPROC_MACSEND_INTERVAL  10000

#define DFC_TIMEOUT 60000

#define MAX_IMSI_RECORDS 50
#define MAX_MAC_RECORDS 50
bool sendInfoToFep = true;
static bool saveImsi = true;
static bool sendInfoToDatam = true;
typedef struct tagPHONEINFO {
    U32 totallen;
    U64 uptime;
    U16 slotId;
    U16 lac;
    char imsi[16];
    char imei[16];
} PHONEINFO;

typedef struct tagMACINFO {
    U32 totallen;
    U64 uptime;
    char mac[12];
} MACINFO;

typedef struct tagPHONEINFOHADNLE {
   U32 recordNum;
   PHONEINFO phoneInfoBuf[MAX_IMSI_RECORDS];
}PHONEINFOHADNLE;

PHONEINFOHADNLE phoneInfoHandle;

typedef struct tagMACINFOHANDLE {
    U32 recordNum;
    MACINFO macInfoBuf[MAX_MAC_RECORDS];
}MACINFOHANDLE;
MACINFOHANDLE macInfoHandle;

DATAPROCSTATS dataprocStats = {0};
static POSTPROCCMD postCmd = NULL_CMD;
static void * postArg = NULL;

sqlite3* membwlistdb = NULL;
char BWdbpath[PATH_MAX];
extern char *data_storage_path;
void* pProcHeartBeatTimer = NULL;
void* pProcSendDataTimer = NULL;
void* pProcSendMacTimer = NULL;

typedef struct tagDATAFLOWCTXT{
    BOOL started;
    U16 dstID;
    LISTTYPE lt;
    RECORDTYPE rt;
    
    char **dbResult;
    int nRow;
    int nColumn;
    int rowIdx;
    
    U32 maxnum;
    //U32 widx;
    //PHONEINFO buff[MAX_DATAPROC_RECORDS];

    void* pTimer;

} DATAFLOWCTXT;


typedef struct tagDATAFLOWPARA {
    U16 dstID;
    LISTTYPE lt;
    RECORDTYPE rt;
    U32 numPerMsg;
}DATAFLOWPARA;

//superset of UEIDPARALIST
typedef struct tagUEIDMODPARALIST {
    char *imsirecord;
    char *imeirecord;
    U32 action;
}UEIDMODPARALIST;

void* DATAPROC_main(void*h);
void DATAPROC_setProc(PCMDHEADER pCmd, PCMDHEADER pAck);
void DATAPROC_getProc(PCMDHEADER pCmd, PCMDHEADER pAck);
void DATAPROC_eventProc(PCMDHEADER pCmd);
void DATAPROC_eventAckProc(PCMDHEADER pCmd);

ERROR_CODE DATAPROC_decodeAction(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE DATAPROC_decodeNumPerMsg(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE DATAPROC_decodeIMSIList(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE DATAPROC_decodeIMEIList(void *h, U8* paraValue, U32 paraLength );

ERROR_CODE DATAPROC_decodeMac(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE DATAPROC_decodeTimestamp(void *h, U8* paraValue, U32 paraLength );
RESULT DATAPROC_initFlowCtrl(DATAFLOWCTXT *dfc);
void DATAPROC_startDataFlow(DATAFLOWCTXT *dfc,DATAFLOWPARA *para);
void DATAPROC_stopDataFlow(DATAFLOWCTXT *dfc);
void DATAPROC_dataFlowLoop(DATAFLOWCTXT *dfc);
void DATAPROC_FlowCtrlTimeout(void *h);
void DATAPROC_sendData();
void DATAPROC_sendMacData(); 

static DATAFLOWCTXT blackIMSIDFC;
static DATAFLOWCTXT blackIMEIDFC;
static DATAFLOWCTXT whiteIMSIDFC;
static DATAFLOWCTXT whiteIMEIDFC;

static DATAFLOWPARA dfcPara;

void DATAPROC_heartbeat_timer(void* h)
{ 
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_DATAPRO, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc);   
     
    MOD_timerRestart(pProcHeartBeatTimer, DATAPROC_HAERTBEAT_INTERVAL);
}

void DATAPROC_sendData_timer(void* h)
{ 
   // U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
   // CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_DATAPRO, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
     //   PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc); 
    if ( phoneInfoHandle.recordNum != 0 )
    {  
        DATAPLogDebug("timeout to sendData %d", phoneInfoHandle.recordNum);
        DATAPROC_sendData();

    }
    MOD_timerRestart(pProcSendDataTimer, DATAPROC_DATASEND_INTERVAL);
}

void DATAPROC_sendMacData_timer(void* h)
{ 
   // U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
   // CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_DATAPRO, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
     //   PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc); 
    if ( macInfoHandle.recordNum != 0 )
    {  
        DATAPLogDebug("timeout to sendData %d", macInfoHandle.recordNum);
        DATAPROC_sendMacData();

    }
    MOD_timerRestart(pProcSendMacTimer, DATAPROC_MACSEND_INTERVAL);
}

static PARADECODERMAP bwDfcParaTable[] = {
    {PARA_TYPE_DATAPROC_NUM_RECORDS_PER_MESSAGE, DATAPROC_decodeNumPerMsg}                      
};


#if 1
PARADECODERMAP UEIDReportTable[5] =
{    
    {PARA_TYPE_EUTRAN_TIME,CM_decodeTimestamp},
    {PARA_TYPE_EUTRAN_UEID_IMSI,CM_decodeIMSI},
    {PARA_TYPE_EUTRAN_UEID_IMEI,CM_decodeIMEI},
    {PARA_TYPE_EUTRAN_BBU_SLOT_ID, CM_decodeSlotId},
    {PARA_TYPE_GSM_LAC, CM_decodeLac}
	
};
#endif

static PARADECODERMAP UEIDActionTable[] =
{    
    {PARA_TYPE_DATAPROC_LIST_ACTION, DATAPROC_decodeAction},
    {PARA_TYPE_DATAPROC_IMSI_DATA, DATAPROC_decodeIMSIList},
    {PARA_TYPE_DATAPROC_IMEI_DATA, DATAPROC_decodeIMEIList},
        
};

static PARADECODERMAP MACReportTable[2] = 
{
    {PARA_TYPE_EUTRAN_TIME, DATAPROC_decodeTimestamp},
    {PARA_TYPE_WIFI_MAC_REPORT, DATAPROC_decodeMac}
};

void DATAPROC_sendMacData()
{
    U64 msgbuff[MSG_BUFF_SIZE/8]={0};
    PMSGHEADER pMsgHeader =(PMSGHEADER) msgbuff;
    PCMDHEADER pCmdHeader = (PCMDHEADER)( ((U8*)msgbuff) + sizeof(MSGHEADER) );
    PPARAM pParam = (PPARAM)(pCmdHeader + 1);
    U8 *paraValue = NULL;
    int i = 0;
    
    pMsgHeader->dstID = MODULE_INTF;
    pMsgHeader->srcID = MODULE_DATAPRO;
    pMsgHeader->msgType = MSG_TYPE_COMMAND;

    pCmdHeader->cmdCode = CMD_CODE_DATAPRO_MAC_INFO;
    pCmdHeader->cmdIndex = gCmdIndex++;
    pCmdHeader->cmdType = CMD_EVENT;
    pCmdHeader->cmdLength = 0; 

        
    for(i=0;i<macInfoHandle.recordNum;i++)
    {
        pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_WIFI_MAC_REPORT,
            macInfoHandle.macInfoBuf[i].totallen,
            &paraValue);
        memcpy(paraValue, &macInfoHandle.macInfoBuf[i].uptime, macInfoHandle.macInfoBuf[i].totallen );
        DATAPLogDebug("send mac is  %s", macInfoHandle.macInfoBuf[i].mac);
    }
    macInfoHandle.recordNum = 0;
    
    pMsgHeader->msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER)+ pCmdHeader->cmdLength;
    CM_sendMsg(pMsgHeader,pCmdHeader);


}

void DATAPROC_sendData()
{
    U64 msgbuff[MSG_BUFF_SIZE/8]={0};
    PMSGHEADER pMsgHeader =(PMSGHEADER) msgbuff;
    PCMDHEADER pCmdHeader = (PCMDHEADER)( ((U8*)msgbuff) + sizeof(MSGHEADER) );
    PPARAM pParam = (PPARAM)(pCmdHeader + 1);
    U8 *paraValue = NULL;
    int i = 0;
    
    pMsgHeader->dstID = MODULE_DATAM;
    pMsgHeader->srcID = MODULE_DATAPRO;
    pMsgHeader->msgType = MSG_TYPE_COMMAND;

    pCmdHeader->cmdCode = CMD_CODE_DATAPRO_PHONE_INFO;
    pCmdHeader->cmdIndex = gCmdIndex++;
    pCmdHeader->cmdType = CMD_EVENT;
    pCmdHeader->cmdLength = 0; 

        
    for(i=0;i<phoneInfoHandle.recordNum;i++)
    {
        pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_DATAPROC_PHONE_INFO,
            phoneInfoHandle.phoneInfoBuf[i].totallen,
            &paraValue);
        memcpy(paraValue, &phoneInfoHandle.phoneInfoBuf[i].uptime, phoneInfoHandle.phoneInfoBuf[i].totallen );

    }
    phoneInfoHandle.recordNum = 0;
    pMsgHeader->msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER)+ pCmdHeader->cmdLength;

    if (sendInfoToDatam)
    {
        CM_sendMsg(pMsgHeader,pCmdHeader);
    }
    //chang dstId
    if (sendInfoToFep)
    {
        pMsgHeader->dstID = MODULE_INTF;
        CM_sendMsg(pMsgHeader,pCmdHeader);
    }
}

ERROR_CODE DATAPROC_decodeTimestamp(void *h, U8* paraValue, U32 paraLength )
{
    MACINFO *buff = (MACINFO*)h;
    if (paraLength == sizeof(U64))
    {
        buff->uptime = *(U64 *)paraValue;
        return PARA_VALUE_ERROR_NO_ERROR;
    }    
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
}

ERROR_CODE DATAPROC_decodeMac(void *h, U8* paraValue, U32 paraLength )
{
    MACINFO *buff = (MACINFO*)h;
    memcpy(buff->mac, (char *)paraValue, 12);
    return PARA_VALUE_ERROR_NO_ERROR;
}

ERROR_CODE DATAPROC_decodeNumPerMsg(void *h, U8* paraValue, U32 paraLength )
{
    U32 *numPerMsg = (U32*)h;

    if(paraLength == sizeof(U32))
    {
        U32 num = *((U32*)paraValue);
        if( (num >0) && (num <= MAX_DATAPROC_RECORDS) )
        {    
            *numPerMsg= num;
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_NUM_OUT_OF_RANGE;
        }
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
}

ERROR_CODE DATAPROC_decodeIMSIList(void *h, U8* paraValue, U32 paraLength )
{
    UEIDMODPARALIST *buff = (UEIDMODPARALIST*)h ;
    memcpy(buff->imsirecord, (char *)paraValue, paraLength );
    return PARA_VALUE_ERROR_NO_ERROR;
}

ERROR_CODE DATAPROC_decodeIMEIList(void *h, U8* paraValue, U32 paraLength )
{
    UEIDMODPARALIST *buff = (UEIDMODPARALIST*)h ;
    buff->imeirecord = (char *)paraValue;
 
    return PARA_VALUE_ERROR_NO_ERROR;
}


ERROR_CODE DATAPROC_decodeAction(void *h, U8* paraValue, U32 paraLength )
{
    UEIDMODPARALIST *buff = (UEIDMODPARALIST*)h ;
    if(paraLength == sizeof(U32))
    {
        switch(*((U32*)paraValue))
        {
            case PARA_VALUE_DATAPROC_ACTION_ADD:                                        
                buff->action = PARA_VALUE_DATAPROC_ACTION_ADD;
                break;
            case PARA_VALUE_DATAPROC_ACTION_DEL:
                buff->action = PARA_VALUE_DATAPROC_ACTION_DEL;
                break;
            default:
                return PARA_VALUE_ERROR_INVALID_PARAVALUE;
                break;
        }
        DATAPLogDebug("action type is %d", *(U32*)paraValue);
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

    return PARA_VALUE_ERROR_NO_ERROR;
}

RESULT DATAPROC_getRecords(DATAFLOWCTXT *dfc)
{
    if(membwlistdb)
    {
        char sql[256]; 
        int rc;
        if(IMSI == dfc->rt)
        {
            sprintf(sql,"SELECT IMSI FROM BLACKWHITE_IMSI WHERE BORW=%u;", dfc->lt);
        }
        else
        {
            sprintf(sql,"SELECT IMEI FROM BLACKWHITE_IMEI WHERE BORW=%u;", dfc->lt);
        }
        DATAPLogNotice("sql cmd is %s \n", sql);
        rc = sqlite3_get_table(membwlistdb,sql,&dfc->dbResult,&dfc->nRow,&dfc->nColumn,NULL);
        if(rc)
        {
            sqlite3_free_table(dfc->dbResult);
            dfc->dbResult = NULL;
            dfc->nRow = 0;
            dfc->nColumn =0;
            DATAPLogError( "Get black/white failed %x", rc);
            return RC_FAIL;
        }
        else
        {
            if(dfc->nRow)
                return RC_OK;
            else
            {
                return RC_FAIL;
            }
        }

    }
    else
    {    
        return RC_FAIL;
    }
}


void DATAPROC_sendDataIndication(DATAFLOWCTXT *dfc)
{
    U64 msgbuff[MSG_BUFF_SIZE/8]={0};
    PMSGHEADER pMsgHeader =(PMSGHEADER) msgbuff;
    PCMDHEADER pCmdHeader = (PCMDHEADER)( ((U8*)msgbuff) + sizeof(MSGHEADER) );
    PPARAM pParam = (PPARAM)(pCmdHeader + 1);
    U8 *paraValue = NULL;
    int i = 0;
    int count = 0;
    U32 pt;

    char nullstring[1]={'\0'};             
    pMsgHeader->dstID = dfc->dstID;
    pMsgHeader->srcID = MODULE_DATAPRO;
    pMsgHeader->msgType = MSG_TYPE_COMMAND;
    
    if(dfc->lt == BLACK)
    {
        if(dfc->rt == IMSI)
        {
            pCmdHeader->cmdCode = CMD_CODE_BLACKLIST_IMSI_DATA;
        }
        else
        {
            pCmdHeader->cmdCode = CMD_CODE_BLACKLIST_IMEI_DATA;
        }
    }
    else
    {
        if(dfc->rt == IMSI)
        {
            pCmdHeader->cmdCode = CMD_CODE_WHITELIST_IMSI_DATA;
        }
        else
        {
            pCmdHeader->cmdCode = CMD_CODE_WHITELIST_IMEI_DATA;
        }

    }
    
    pCmdHeader->cmdIndex = gCmdIndex++;
    pCmdHeader->cmdType = CMD_EVENT;
    pCmdHeader->cmdLength = 0; 



    if(((dfc->nRow - dfc->rowIdx)) <= dfc->maxnum)
    {
        count =  dfc->nRow - dfc->rowIdx;
    }
    else
    {
        count =  dfc->maxnum ;
    }

    if(dfc->rt == IMSI)
    {
        pt = PARA_TYPE_DATAPROC_RECORD_IMSI; 
    }
    else
    {
        pt = PARA_TYPE_DATAPROC_RECORD_IMEI;
    }

    
    pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_DATAPROC_HAS_MORE_DATA,sizeof(U32),&paraValue);
    *((U32*)paraValue) = ((dfc->rowIdx+count) == dfc->nRow)?FALSE:TRUE;

    for(i=0;i<count;i++)
    {
        char *dbResult = dfc->dbResult[++dfc->rowIdx];
        char *result = dbResult==NULL?nullstring:dbResult;
        U32 len = strlen(result)+1;
        pCmdHeader->cmdLength += CM_paraPackPara(&pParam,pt,len,&paraValue);
        memcpy(paraValue,result,len);

    }
    
    pMsgHeader->msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER) + pCmdHeader->cmdLength;
    CM_sendMsg(pMsgHeader,pCmdHeader);
}

void DATAPROC_stopDataFlow(DATAFLOWCTXT *dfc)
{
    if(dfc->dbResult)
        sqlite3_free_table(dfc->dbResult);

    dfc->dbResult = NULL;
    dfc->dstID = 0;    
    dfc->started = FALSE;
    
    //dfc->widx = 0;
    dfc->rowIdx = 0;
    dfc->nRow = 0;
    
}

void DATAPROC_FlowCtrlTimeout(void *h)
{
    DATAFLOWCTXT *dfc = (DATAFLOWCTXT *)h;
    if(dfc->started)
    {
        DATAPROC_stopDataFlow(dfc);
    }
}




void DATAPROC_dataFlowLoop(DATAFLOWCTXT *dfc)
{

    if(dfc->nRow > 0)
    {
        DATAPROC_sendDataIndication(dfc);
        
        if(dfc->rowIdx == dfc->nRow)
        {
            if(dfc->dbResult)
                sqlite3_free_table(dfc->dbResult);

            dfc->dbResult = NULL;
            dfc->rowIdx = 0;  
            dfc->started = FALSE;
        }
        else
        {
            dfc->pTimer = MOD_timerStart(MODULE_DATAPRO,DFC_TIMEOUT,DATAPROC_FlowCtrlTimeout,dfc);
        
        }

    }

    
}

void DATAPROC_startDataFlow(DATAFLOWCTXT *dfc,DATAFLOWPARA *para)
{
    dfc->dstID = para->dstID;
    dfc->maxnum = para->numPerMsg;
    dfc->lt = para->lt;
    dfc->rt = para->rt;
    
    dfc->rowIdx = 0;
    //dfc->widx = 0;

    dfc->nColumn = 0;
    dfc->nRow = 0;
    
    if(DATAPROC_getRecords(dfc) != RC_OK)
    {
        DATAPROC_sendDataIndication(dfc);
        return;
    }
    
    dfc->started = TRUE;
            
    DATAPROC_dataFlowLoop(dfc);

}



RESULT DATAPROC_initFlowCtrl(DATAFLOWCTXT *dfc)
{
    dfc->started = FALSE;
    dfc->dstID = 0;
    //dfc->widx = 0;
    dfc->rowIdx = 0;
    dfc->nRow = 0;
    dfc->nColumn = 0;
    dfc->dbResult = NULL;
    dfc->pTimer = NULL;
    
                
    return RC_OK;
}

int DATAPROC_copyIMSICB(void * para, int n_column, char ** column_value, char ** column_name)
{
    sqlite3* memdb=(sqlite3*)para;
    char sql[256];
    sprintf(sql,"INSERT INTO BLACKWHITE_IMSI VALUES(%s,%s);", column_value[0], column_value[1]);
    sqlite3_exec(memdb,sql,0,0,NULL);
    return 0;
}

int DATAPROC_copyIMEICB(void * para, int n_column, char ** column_value, char ** column_name)
{
    sqlite3* memdb=(sqlite3*)para;
    char sql[256];
    sprintf(sql,"INSERT INTO BLACKWHITE_IMEI VALUES(%s,%s);", column_value[0], column_value[1]);
    sqlite3_exec(memdb,sql,0,0,NULL);
    return 0;
}

RESULT DATAPROC_appendRecord(sqlite3 *db ,LISTTYPE lt, RECORDTYPE rt, char* record)
{
    char sql[256]; 
    int rc;
    if(IMSI == rt)
    {
        sprintf(sql,"INSERT INTO BLACKWHITE_IMSI VALUES(%s,%u);", record, lt);
    }
    else
    {
        sprintf(sql,"INSERT INTO BLACKWHITE_IMEI VALUES(%s,%u);", record, lt);
    }

    rc = sqlite3_exec(db,sql,NULL,NULL,NULL );
    if(rc)
        return RC_FAIL;
    else
        return RC_OK;
}


RESULT DATAPROC_deleteRecord(sqlite3 *db, LISTTYPE lt, RECORDTYPE rt, char* record)
{
    char sql[256]; 
    int rc;
    
    if(IMSI == rt)
    {
        sprintf(sql,"DELETE FROM BLACKWHITE_IMSI WHERE IMSI = %s and BORW = %u;", record,lt);
    }
    else
    {
        sprintf(sql,"DELETE FROM BLACKWHITE_IMEI WHERE IMEI = %s and BORW = %u;", record,lt);
    }

    rc = sqlite3_exec(db,sql,NULL,NULL,NULL );
    if(rc)
        return RC_FAIL;
    else
        return RC_OK;

}


int DATAPROC_searchCB(void * para, int n_column, char ** column_value, char ** column_name)
{
   //*((int *)para) = *((int *)para) + 1 ;
   *((LISTTYPE*)para) = atoi(column_value[1]);
    
   return 0;
}

RESULT DATAPROC_searchRecord(sqlite3 *db,LISTTYPE* lt, RECORDTYPE rt, char* record)
{
    char sql[256]; 
    *lt = INVALID_LISTTYPE;
    
    if(IMSI == rt)
    {
        sprintf(sql,"SELECT * FROM BLACKWHITE_IMSI WHERE IMSI = %s;", record);
    }
    else
    {
        sprintf(sql,"SELECT * FROM BLACKWHITE_IMEI WHERE IMEI = %s;", record);
    }

    sqlite3_exec(db,sql,DATAPROC_searchCB,lt,NULL);
    if((*lt) == INVALID_LISTTYPE)
        return RC_FAIL;
    else
        return RC_OK;

}


int DATAPROC_getCB(void * para, int n_column, char ** column_value, char ** column_name)
{
   //*((int *)para) = *((int *)para) + 1 ;
   *((LISTTYPE*)para) = atoi(column_value[1]);
    
   return 0;
}

RESULT DATAPROC_getRecord(sqlite3 *db,LISTTYPE lt, RECORDTYPE rt,char*** result, int* nrow,int*ncol)
{
    char sql[256]; 
    int rc;
    
    if(IMSI == rt)
    {
        sprintf(sql,"SELECT IMSI FROM BLACKWHITE_IMSI WHERE lt = %u;", lt);
    }
    else
    {
        sprintf(sql,"SELECT IMEI FROM BLACKWHITE_IMEI WHERE lt = %u;", lt);
    }

    rc = sqlite3_get_table(db,sql,result,nrow,ncol,NULL);
    if(rc)
        return RC_FAIL;
    else
        return RC_OK; 

}



#define RECORD_MASK    0x0FFFFFFFFFFFFFFFLL
#define INVALID_ACTION 2
void DATAPROC_listConfig(PCMDHEADER pCmd, PCMDHEADER pAck, LISTTYPE listType)
{    
    sqlite3* db;
    int sqlrc;

    UEIDMODPARALIST paraList = {0};
    char list[256] = {0};
    paraList.imsirecord = list;
    if(RC_OK == CM_paraListDecoder(pCmd,pAck, UEIDActionTable,sizeof(UEIDActionTable)/sizeof(PARADECODERMAP),&paraList,FALSE))
    {
        //check whether all parameters are provided     
        if( ((paraList.imsirecord != NULL) || (paraList.imeirecord != NULL))
           && (paraList.action != INVALID_ACTION))
        {
            sqlrc = sqlite3_open(BWdbpath,&db);
            if(sqlrc )
            {
                pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_OPEN_DATABASE_FAILED);
                DATAPLogError("Can't open database: %s", sqlite3_errmsg(db));
            }
            else
            {
                if(paraList.action == PARA_VALUE_DATAPROC_ACTION_ADD)
                {
                    int rc = 0;
                    if( paraList.imsirecord != NULL)
                    {
                        char *splt_list = NULL;
                        splt_list = strtok(paraList.imsirecord, ",");
                          
                        if (splt_list != NULL)
                        {
                                             
                            rc += DATAPROC_appendRecord(db,listType,IMSI,splt_list);
                            rc += DATAPROC_appendRecord(membwlistdb,listType,IMSI,splt_list);
                          
                        }
                        while((splt_list = strtok(NULL, ",")) != NULL)
                        {
                 
                        
                            rc += DATAPROC_appendRecord(db,listType,IMSI,splt_list);
                            rc += DATAPROC_appendRecord(membwlistdb,listType,IMSI,splt_list);
                             
                          
                        }  
                                             
                    }

                    if( paraList.imeirecord != NULL)
                    {
                        char *splt_list = NULL;
                        splt_list = strtok(paraList.imsirecord, ",");
                        if (splt_list != NULL)
                        {
                            
                            rc += DATAPROC_appendRecord(db,listType,IMEI,splt_list);
                            rc += DATAPROC_appendRecord(membwlistdb,listType,IMEI,splt_list);
                    
                        }
                        while((splt_list = strtok(NULL, ",")) != NULL)
                        {
                            
                            rc += DATAPROC_appendRecord(db,listType,IMEI,splt_list);
                            rc += DATAPROC_appendRecord(membwlistdb,listType,IMEI,splt_list);
                       
                        }  
                    }                     

                    if(rc )
                    {    //rollback all if error
                        if( paraList.imsirecord != NULL)
                        {
                            char *splt_list = NULL;
                            splt_list = strtok(paraList.imsirecord, ",");
                            if (splt_list != NULL)
                            {
                                rc += DATAPROC_deleteRecord(db,listType,IMSI,splt_list);
                                rc += DATAPROC_deleteRecord(membwlistdb,listType,IMSI,splt_list);
 
                               
                            }
                            while((splt_list = strtok(NULL, ",")) != NULL)
                            {
                               
                                rc += DATAPROC_deleteRecord(db,listType,IMSI,splt_list);
                                rc += DATAPROC_deleteRecord(membwlistdb,listType,IMSI,splt_list);
                                   
                               
                            } 
                            
                        }
                        
                        if( paraList.imeirecord != NULL)
                        {
                            char *splt_list = NULL;
                            splt_list = strtok(paraList.imsirecord, ",");
                            if (splt_list != NULL)
                            {
                            
                                rc += DATAPROC_deleteRecord(db,listType,IMSI,splt_list);
                                rc += DATAPROC_deleteRecord(membwlistdb,listType,IMSI,splt_list);
                              
                            }
                            while((splt_list = strtok(NULL, ",")) != NULL)
                            {
                            
                                rc += DATAPROC_deleteRecord(db,listType,IMSI,splt_list);
                                rc += DATAPROC_deleteRecord(membwlistdb,listType,IMSI,splt_list);
                               
                            } 
                        } 

                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_INSERT_RECORD_FAILED);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);   
                    }
                }
                else
                {
                    int rc = 0;
                    if( paraList.imsirecord != NULL)
                    {
                        rc += DATAPROC_deleteRecord(db,listType,IMSI,paraList.imsirecord);
                        rc += DATAPROC_deleteRecord(membwlistdb,listType,IMSI,paraList.imsirecord);
                        
                    }

                    if( paraList.imeirecord != NULL)
                    {
                        rc += DATAPROC_deleteRecord(db,listType,IMEI,paraList.imeirecord);
                        rc += DATAPROC_deleteRecord(membwlistdb,listType,IMEI,paraList.imeirecord);
                    }                     
                    
                    if(rc )
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_INSERT_RECORD_FAILED);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);   
                    }

                }
            }
            sqlite3_close(db);
        }
        else
        {
            //not enough parameters
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
        }
    }

    
}


void DATAPROC_listDFCmd_start(PCMDHEADER pCmd, PCMDHEADER pAck, DATAFLOWCTXT *dfc,LISTTYPE lt,RECORDTYPE rt)
{
    PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
    U32 numPerMsg = 0;
    if(RC_OK == CM_paraListDecoder(pCmd,pAck, bwDfcParaTable,sizeof(bwDfcParaTable)/sizeof(PARADECODERMAP),&numPerMsg,FALSE)) 
    {
        if(numPerMsg == 0)
        {
            numPerMsg = 30;
        }
        
        if(dfc->started)
        {
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_BWLIST_DATAFLOW_BUSY);
            DATAPLogError("Error in cmdType=%02x cmdCode=%04x. Error=%x",pCmd->cmdType,pCmd->cmdCode,PARA_VALUE_ERROR_BWLIST_DATAFLOW_BUSY);
            return;
        }
        
        dfcPara.dstID = pMsgHdr->srcID;
        dfcPara.lt = lt;
        dfcPara.rt = rt;
        dfcPara.numPerMsg = numPerMsg;
        postArg = dfc;
        postCmd = START_DFC;
        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);   

    }
}

void DATAPROC_listDFCmd_stop(PCMDHEADER pCmd, PCMDHEADER pAck, DATAFLOWCTXT *dfc,LISTTYPE lt,RECORDTYPE rt)
{
      PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
      if(dfc->started)
      {
          if(pMsgHdr->srcID == dfc->dstID)
          {
              MOD_timerClear(MODULE_DATAPRO,dfc->pTimer);
              dfc->pTimer= NULL;
              DATAPROC_stopDataFlow(dfc);
              
              pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS); 
          }
          else
          {
              pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_NOT_BWLISTG_DATAFLOW_PEER);
          }
          
      }
      else
      {
          pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS); 
      }
}

void DATAPROC_listDFCmd_next(PCMDHEADER pCmd, DATAFLOWCTXT *dfc)
{
    PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));

    if((dfc->started) && (dfc->dstID == pMsgHdr->srcID))
    {

        MOD_timerClear(MODULE_DATAPRO,dfc->pTimer);
        dfc->pTimer = NULL;
                
        DATAPROC_dataFlowLoop(dfc);
        
    }
}

void DATAPROC_setProc(PCMDHEADER pCmd, PCMDHEADER pAck)
{    
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BLACKLIST_CONFIG:
            DATAPROC_listConfig(pCmd,pAck,BLACK);
            break;
        case CMD_CODE_WHITELIST_CONFIG:
            DATAPROC_listConfig(pCmd,pAck,WHITE);
            break;
        case CMD_CODE_BLACKLIST_IMSI_TRANSFER_START:
            DATAPROC_listDFCmd_start(pCmd, pAck, &blackIMSIDFC,BLACK, IMSI);            
            break;
        case CMD_CODE_BLACKLIST_IMSI_TRANSFER_STOP:
            DATAPROC_listDFCmd_stop(pCmd, pAck, &blackIMSIDFC,BLACK, IMSI);                      
            break;
        case CMD_CODE_BLACKLIST_IMEI_TRANSFER_START:
            DATAPROC_listDFCmd_start(pCmd, pAck, &blackIMEIDFC,BLACK, IMEI);            
            break;
        case CMD_CODE_BLACKLIST_IMEI_TRANSFER_STOP:
            DATAPROC_listDFCmd_stop(pCmd, pAck, &blackIMEIDFC,BLACK, IMEI);            
            break;
        case CMD_CODE_WHITELIST_IMSI_TRANSFER_START:
            DATAPROC_listDFCmd_start(pCmd, pAck, &whiteIMSIDFC,WHITE, IMSI);                        
            break;
        case CMD_CODE_WHITELIST_IMSI_TRANSFER_STOP:
            DATAPROC_listDFCmd_stop(pCmd, pAck, &whiteIMSIDFC,WHITE, IMSI);                        
            break;
        case CMD_CODE_WHITELIST_IMEI_TRANSFER_START:
            DATAPROC_listDFCmd_start(pCmd, pAck, &whiteIMEIDFC,WHITE, IMEI);            
            break;
        case CMD_CODE_WHITELIST_IMEI_TRANSFER_STOP:
            DATAPROC_listDFCmd_stop(pCmd, pAck, &whiteIMEIDFC,WHITE, IMEI);            
            break;

        case CMD_CODE_SET_UPLOAD_MODE:
          {
            UNPACK_RESULT uprc;
            PPARAM pParam =(PPARAM)(pCmd+1);
            uint32_t len = pCmd->cmdLength;
            uint32_t paraType;
            uint32_t paraLength = 0;
            uint8_t* paraValue = NULL;

            
            while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
            {
                 if( paraType==PARA_TYPE_DATAPROC_UPLOAD_MODE )
                 {
                     if ( *(U32 *)paraValue != PARA_VALUE_DATAPROC_MODE_NORMAL && *(U32 *)paraValue !=  PARA_VALUE_DATAPROC_NOT_SAVE_DATAM)
                     {

                         sendInfoToFep = false;
                     }
                     else
                     {
                         sendInfoToFep = true;
                     }
                     if ( *(U32 *)paraValue == PARA_VALUE_DATAPROC_NOT_SAVE_IMSI)
                     {
                         saveImsi = false;
                     }
                     else
                     {
                         saveImsi = true;
                     }
                     if ( *(U32 *)paraValue ==  PARA_VALUE_DATAPROC_NOT_SAVE_DATAM)
                     {
                         sendInfoToDatam = false;
                     }
                     DATAPLogNotice( "set upload mode is %d ", *(U32 *)paraValue);
                     pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1), PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS); 
                 }
                 else
                 {
                     DATAPLogNotice( "set upload mode para error ");
                     pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
                 }
            }
            break;
           } 
#ifdef MODULE_TEST
//here is test heartbeat
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            DATAPLogWarning( "----- test module datapro ----- %04x", CMD_CODE_SYSMONITOR_TEST_MODULE);
            while(1)
            {

            }
            break;
#endif
        default:
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);
            DATAPLogError("Unknown SET cmd cmdCode=%04x",pCmd->cmdCode);
            break;

    }

}

void DATAPROC_getProc(PCMDHEADER pCmd, PCMDHEADER pAck)
{
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BLACKLIST_CONFIG:
            

            //break;
        case CMD_CODE_WHITELIST_CONFIG:
            //silent drop
            
            //break;
        default:
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);            
            DATAPLogError("Unknown GET cmd cmdCode=%04x",pCmd->cmdCode);
            break;        
    }


}

void DATAPROC_postProc(void)
{
    switch (postCmd)
    {
        case NULL_CMD:
            break;
        case START_DFC:
            DATAPROC_startDataFlow(postArg,&dfcPara);
            break;
        default :
            break;
    }

    postCmd = NULL_CMD;

        
}

void DATAPROC_send_blackalert(U64 uptime,char *imsirecord, char *imeirecord)
{
    U64 msgbuff[MSG_BUFF_SIZE/8]={0};
    PMSGHEADER pMsgHeader =(PMSGHEADER) msgbuff;
    PCMDHEADER pCmdHeader = (PCMDHEADER)(((U8*)msgbuff) + sizeof(MSGHEADER) );
    PPARAM pParam = (PPARAM)(pCmdHeader + 1);
    U8 *paraValue = NULL;

    if( (imsirecord == NULL) && (imsirecord == NULL) )
    {
        return;
    }
    
    pMsgHeader->dstID = MODULE_INTF;
    pMsgHeader->srcID = MODULE_DATAPRO;
    pMsgHeader->mType = get_mtype(pMsgHeader->dstID);
    pMsgHeader->msgType = MSG_TYPE_COMMAND;

    pCmdHeader->cmdCode = CMD_CODE_BLACKLIST_ALERT;
    pCmdHeader->cmdIndex = gCmdIndex++;
    pCmdHeader->cmdType = CMD_EVENT;
    pCmdHeader->cmdLength = 0; 

    pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_TIMESTAMP,sizeof(U64),&paraValue);
    *((U64*)paraValue) = uptime;

    if(imsirecord != NULL)
    {   
        pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_DATAPROC_RECORD_IMSI,16,&paraValue);
        memcpy(paraValue, imsirecord,16);
    }

    
    if(imeirecord != NULL)
    {   
        pCmdHeader->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_DATAPROC_RECORD_IMEI,16,&paraValue);
        memcpy(paraValue, imeirecord,16);
    }
 
    pMsgHeader->msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER) + pCmdHeader->cmdLength;
    if(RC_OK == CM_sendMsg(pMsgHeader,pCmdHeader))
    {
        dataprocStats.numBlackAlertSent++;
    }
    else
    {
        dataprocStats.numBlackAlertSendFailed++;
    }
}


//for indication, error do nothing
void DATAPROC_ueIDReport(PCMDHEADER pCmd)
{

    UEIDPARALIST paraList = {0};
   
    if(RC_OK == CM_paraListDecoder(pCmd,NULL, UEIDReportTable,sizeof(UEIDReportTable)/sizeof(PARADECODERMAP),&paraList,TRUE))
    {
        LISTTYPE imsiListType = INVALID_LISTTYPE;
        LISTTYPE imeiListType = INVALID_LISTTYPE;

#if 1     
        if(paraList.uptime == 0)
        {
            
            DATAPLogError("Error in cmdType=%02x cmdCode=%04x. Error=%x",pCmd->cmdType,pCmd->cmdCode,PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
            return;
        }
 #endif       
        if((paraList.imsirecord == NULL) && (paraList.imeirecord == NULL))
        {
            DATAPLogError("Error in cmdType=%02x cmdCode=%04x. Error=%x",pCmd->cmdType,pCmd->cmdCode,PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
            return;
        }        
        dataprocStats.numUEIDRecvd++;
        
        if( paraList.imsirecord != NULL)
        {
            DATAPROC_searchRecord(membwlistdb,&imsiListType,IMSI,paraList.imsirecord);            
            
        }
    
        if( paraList.imeirecord != NULL)
        {
            //
            DATAPROC_searchRecord(membwlistdb,&imeiListType,IMEI,paraList.imeirecord);
             
        }    

        
        if((imsiListType != WHITE) && (imeiListType != WHITE))
        {

            //*forwardDest = MODULE_DATAM;
#if 0
            PMSGHEADER pMsgHeader =(PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
            if(RC_OK == MSG_send(MODULE_DATAM,pMsgHeader,pCmd))
            {
                dataprocStats.numUEIDforwarded++;
            }
            else
            {
                dataprocStats.numUEIDforwardFailed++;
            }
#endif
           char nchar[1]={'\0'}; 
           PHONEINFO *record =  &phoneInfoHandle.phoneInfoBuf[phoneInfoHandle.recordNum++];
           if ( record != NULL )
           {
               record->uptime = paraList.uptime;
               strcpy(record->imsi, (strlen(paraList.imsirecord)==0? nchar:paraList.imsirecord));
               strcpy(record->imei, (strlen(paraList.imeirecord)==0? nchar:paraList.imeirecord));
               record->slotId = paraList.slotId;
               record->lac = paraList.lac;
               record->totallen = sizeof(U64) + sizeof(int) + strlen(record->imsi)+strlen(record->imei) + 2;
              
           }
           if ( phoneInfoHandle.recordNum == MAX_IMSI_RECORDS )
           {
               DATAPROC_sendData();
           }
            

            //alarm
             DATAPROC_send_blackalert(paraList.uptime,(imsiListType == BLACK)? paraList.imsirecord:NULL, (imeiListType == BLACK)? paraList.imeirecord:NULL );
        }
        else
        {
            dataprocStats.numWhiteDropped++;
             DATAPLogError("Error in cmdType=%02x cmdCode=%04x.",pCmd->cmdType,pCmd->cmdCode);

        }
    }
}


void DATAPROC_macReport(PCMDHEADER pCmd)
{
    MACINFO paraList= {0};
    if(RC_OK == CM_paraListDecoder(pCmd,NULL, MACReportTable,sizeof(MACReportTable)/sizeof(PARADECODERMAP),&paraList,TRUE))
    {
        if ( paraList.uptime == 0 )
        {
            DATAPLogError("Error in cmdType=%02x cmdCode=%04x. Error=%x",pCmd->cmdType,pCmd->cmdCode,PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
            return;
        }
        if ( paraList.mac == NULL || strlen(paraList.mac) == 0 ) 
        {
            DATAPLogError("Error in cmdType=%02x cmdCode=%04x. Error=%x",pCmd->cmdType,pCmd->cmdCode,PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
            return;
        }
        MACINFO *record =  &macInfoHandle.macInfoBuf[macInfoHandle.recordNum++];
        if ( record != NULL )
        {
            record->uptime = paraList.uptime;
            strcpy(record->mac, paraList.mac);
            record->totallen = sizeof(U64) + 12;
              
        }
        if ( macInfoHandle.recordNum == MAX_MAC_RECORDS )
        {
            DATAPROC_sendMacData();
        }        
    }
}

void DATAPROC_eventProc(PCMDHEADER pCmd)
{
    switch(pCmd->cmdCode)
    {
        case CMD_EVT_EUTRAN_UEID:
            if (saveImsi)
            {
                DATAPROC_ueIDReport(pCmd);
            }
            break;

        case CMD_EVT_WIFI_MAC:
            DATAPROC_macReport(pCmd);
            break;

        default:
            DATAPLogError("Unknown EVENT cmdCode=%04x",pCmd->cmdCode);            
            break;
        
    }

}


void DATAPROC_eventAckProc(PCMDHEADER pCmd)
{
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BLACKLIST_IMSI_DATA:
            DATAPROC_listDFCmd_next(pCmd,&blackIMSIDFC);
            break;
        case CMD_CODE_BLACKLIST_IMEI_DATA:
            DATAPROC_listDFCmd_next(pCmd,&blackIMEIDFC);
            break;
        case CMD_CODE_WHITELIST_IMSI_DATA:
            DATAPROC_listDFCmd_next(pCmd,&whiteIMSIDFC);
            break;
        case CMD_CODE_WHITELIST_IMEI_DATA:
            DATAPROC_listDFCmd_next(pCmd,&whiteIMEIDFC);
            break;
        default:
            DATAPLogError("Unknown EVENT cmdCode=%04x",pCmd->cmdCode);            
            break;
        

    }

}


void* DATAPROC_main(void*h)
{
    pthread_setname_np(pthread_self(), "dataproc");

    CMMODINFO cmModInfo = {0};

    DATAPROC_initFlowCtrl(&blackIMSIDFC);
    DATAPROC_initFlowCtrl(&blackIMEIDFC);
    DATAPROC_initFlowCtrl(&whiteIMSIDFC);
    DATAPROC_initFlowCtrl(&whiteIMEIDFC);

    pProcHeartBeatTimer = MOD_timerStart(MODULE_DATAPRO, DATAPROC_HAERTBEAT_INTERVAL, DATAPROC_heartbeat_timer, NULL);

    pProcSendDataTimer = MOD_timerStart(MODULE_DATAPRO, DATAPROC_DATASEND_INTERVAL, DATAPROC_sendData_timer, NULL);

    pProcSendMacTimer = MOD_timerStart(MODULE_DATAPRO, DATAPROC_MACSEND_INTERVAL, DATAPROC_sendMacData_timer, NULL);

    
    cmModInfo.ModID = MODULE_DATAPRO;
    cmModInfo.useTimer = TRUE;
    cmModInfo.setProc = DATAPROC_setProc;
    cmModInfo.getProc = DATAPROC_getProc;
    cmModInfo.eventProc = DATAPROC_eventProc;
    cmModInfo.eventAckProc = DATAPROC_eventAckProc;
    cmModInfo.postProc = DATAPROC_postProc;
    
    CM_cmdDispatcher(&cmModInfo);
    
    return NULL;
}


RESULT DATAPROC_init(void)
{
    pthread_t pthrd;
    MODREG modReg = {0};
    sqlite3 *db=NULL;
    //sqlite3 *memdb=NULL;
    int rc;
    char *sql=NULL;
    //char *errMsg = NULL;

    modReg.modID = MODULE_DATAPRO;
    modReg.needTick = TRUE;
    modReg.tickPeriod = DATAPROC_TIMER_RESOLUTION; // 5s
    modReg.needModTimer = TRUE;

    MOD_register(&modReg);

    sprintf(BWdbpath,"%s/BWlist.db",data_storage_path);
    
    rc = sqlite3_open(BWdbpath,&db);
    if(rc )
    {
        DATAPLogError("Can't open datbase file %s: %s", BWdbpath,sqlite3_errmsg(db));
        sqlite3_close(db);
        return RC_FAIL;
    }

    
    rc = sqlite3_open(":memory:",&membwlistdb);
    if(rc )
    {
        DATAPLogError("Can't open database: %s", sqlite3_errmsg(membwlistdb));
        //memdb will be NULL if failed
        return RC_FAIL;
    }

    sql= "CREATE TABLE IF NOT EXISTS BLACKWHITE_IMSI( \
         IMSI INTEGER PRIMARY KEY, \
         BORW INTEGER \
        );";

    sqlite3_exec(db,sql,0,0,NULL);

    sql= "CREATE TABLE IF NOT EXISTS BLACKWHITE_IMEI( \
         IMEI INTEGER PRIMARY KEY, \
         BORW INTEGER \
        );";

    sqlite3_exec(db,sql,0,0,NULL);

    sql= "CREATE TABLE IF NOT EXISTS BLACKWHITE_IMSI( \
         IMSI INTEGER PRIMARY KEY,\
         BORW INTEGER\
        );";

    sqlite3_exec(membwlistdb,sql,0,0,NULL);

    sql= "CREATE TABLE IF NOT EXISTS BLACKWHITE_IMEI(\
         IMEI INTEGER PRIMARY KEY,\
         BORW INTEGER\
        );";

    sqlite3_exec(membwlistdb,sql,0,0,NULL);



    //copy imsi  and imei table
    sql="SELECT * FROM BLACKWHITE_IMSI;";    
    rc = sqlite3_exec(db,sql,DATAPROC_copyIMSICB,membwlistdb,NULL);
    sql="SELECT * FROM BLACKWHITE_IMEI;";   
    sqlite3_exec(db,sql,DATAPROC_copyIMEICB,membwlistdb,NULL);

    sqlite3_close(db);
     
    phoneInfoHandle.recordNum = 0;
       
    pthread_create(&pthrd, NULL, DATAPROC_main, NULL);

    return RC_OK;
}

void DATAPROC_printStats(void)
{
    dbgprintf_s(DEBUG_INFO, stdout, "**********     MODID[0x%x] Data Processor statistics (dec) ***************\n ", MODULE_DATAPRO);
    dbgprintf_s(DEBUG_INFO, stdout, "UEIDRcvd = %u, UEIDForwarded = %u UEIDForwardedFailed = %u\n  ",dataprocStats.numUEIDRecvd,dataprocStats.numUEIDforwarded,dataprocStats.numUEIDforwardFailed);
    dbgprintf_s(DEBUG_INFO, stdout, "BlackAlert = %u BlackAlertFailed = %u, WhiteDropped = %u\n",dataprocStats.numBlackAlertSent,dataprocStats.numBlackAlertSendFailed,dataprocStats.numWhiteDropped);
}


